﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FrameWorkCore.StackExchangeRedis
{
    public class StackExchangeRedisBuilder
    {

        private readonly static object cLock = new object();
        private static ConnectionMultiplexer RedisInstance ;
        private IConfiguration _Configuration;
        private ILogger<StackExchangeRedisBuilder> _Logger;

        public StackExchangeRedisBuilder(IConfiguration Configuration, ILogger<StackExchangeRedisBuilder> Logger)
        {
            _Configuration = Configuration;
            _Logger = Logger;
            RedisInstance = RedisInit();
        }


        private ConnectionMultiplexer RedisInit()
        {

            var connect = ConnectionMultiplexer.Connect(_Configuration.GetValue<string>("RedisServer"));
                connect.ConnectionFailed += MuxerConnectionFailed;
                connect.ConnectionRestored += MuxerConnectionRestored;
                connect.ErrorMessage += MuxerErrorMessage;
                connect.ConfigurationChanged += MuxerConfigurationChanged;
                connect.HashSlotMoved += MuxerHashSlotMoved;
                connect.InternalError += MuxerInternalError;

            return connect;
        }


        public ConnectionMultiplexer GetRedisInstance
        {
            get
            {
                if (RedisInstance == null)
                    lock (cLock)
                    {
                        if (RedisInstance == null || !RedisInstance.IsConnected)
                            RedisInstance = RedisInit();
                    }

                return RedisInstance;
            }
        }

        #region 事件

        /// <summary>
        /// 配置更改时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
            => _Logger.LogTrace($"Redis Configuration changed:{e.EndPoint}");

        /// <summary>
        /// 发生错误时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
            => _Logger.LogError($"Redis ErrorMessage:{e.Message}");

        /// <summary>
        /// 重新建立连接之前的错误
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
             => _Logger.LogError($"Redis ConnectionRestored:{e.EndPoint}");

        /// <summary>
        /// 连接失败 ， 如果重新连接成功你将不会收到这个通知
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
            => _Logger.LogError($"Redis Endpoint failed:{e.EndPoint},{e.FailureType} {(e.Exception == null ? "" : $", {e.Exception.Message}")}");

        /// <summary>
        /// 更改集群
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
            => _Logger.LogTrace($"HashSlotMoved:NewEndPoint{e.NewEndPoint}, OldEndPoint{e.OldEndPoint}");

        /// <summary>
        /// redis类库错误
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MuxerInternalError(object sender, InternalErrorEventArgs e)
            => _Logger.LogError($"InternalError:Message{e.Exception.Message}");

        #endregion 事件
    }
}
